package net.lgy.controller;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.enums.ParameterIn;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.tags.Tag;
import net.lgy.annotation.ShareCodeCheck;
import net.lgy.aspect.ShareCodeAspect;
import net.lgy.controller.req.*;
import net.lgy.dto.*;
import net.lgy.enums.BizCodeEnum;
import net.lgy.interceptor.LoginInterceptor;
import net.lgy.service.ShareService;
import net.lgy.util.JsonData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * 分享功能控制器
 * 负责处理与分享相关的HTTP请求，包括查询个人分享列表、创建分享链接和取消分享
 */
@Tag(name = "分享管理", description = "提供分享链接的创建、查询和取消功能")
@RestController
@RequestMapping("/api/share/v1")
public class ShareController {

    /**
     * 注入分享服务层对象，用于处理业务逻辑
     */
    @Autowired
    private ShareService shareService;

    /**
     * 获取当前登录用户的个人分享列表
     * 接口功能：查询当前用户创建的所有分享记录
     * 权限要求：登录用户
     *
     * @return JsonData 响应结果，包含分享列表数据或错误信息
     */
    @Operation(
            summary = "获取个人分享列表",
            description = "查询当前登录用户创建的所有有效分享记录，返回分享链接及相关信息",
            method = "GET"
    )
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "获取成功",
                    content = @Content(schema = @Schema(implementation = JsonData.class))),
            @ApiResponse(responseCode = "500", description = "服务器内部错误",
                    content = @Content(schema = @Schema(implementation = JsonData.class)))
    })
    @GetMapping("/list")
    public JsonData listMyShare() {
        // 调用服务层方法获取个人分享列表
        List<ShareDTO> shareDTOS = shareService.listMyShare();

        // 根据查询结果返回成功或错误响应
        return shareDTOS != null ? JsonData.buildSuccess(shareDTOS) : JsonData.buildError("获取分享列表失败");
    }

    /**
     * 创建分享链接
     * 接口功能：为指定资源创建新的分享链接
     * 权限要求：登录用户
     *
     * @param request 包含分享资源信息的请求对象
     * @return JsonData 响应结果，包含新创建的分享信息或错误信息
     */
    @Operation(
            summary = "创建分享链接",
            description = "为指定资源创建新的分享链接，需要传入资源ID和分享有效期等参数",
            method = "POST",
            requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
                    description = "分享创建请求参数",
                    required = true,
                    content = @Content(schema = @Schema(implementation = ShareCreateRequest.class))
            )
    )
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "创建成功",
                    content = @Content(schema = @Schema(implementation = JsonData.class))),
            @ApiResponse(responseCode = "400", description = "参数错误",
                    content = @Content(schema = @Schema(implementation = JsonData.class))),
            @ApiResponse(responseCode = "500", description = "服务器内部错误",
                    content = @Content(schema = @Schema(implementation = JsonData.class)))
    })
    @PostMapping("/create")
    public JsonData createShare(
            @Parameter(required = true, description = "分享创建请求对象，包含资源ID和有效期等信息")
            @RequestBody ShareCreateRequest request) {
        // 从ThreadLocal中获取当前登录用户ID并设置到请求对象中
        Long accountNo = LoginInterceptor.threadLocal.get().getAccountNo();
        request.setAccountNo(accountNo);

        // 调用服务层方法创建分享
        ShareDTO shareDTO = shareService.createShare(request);

        // 根据创建结果返回成功或错误响应
        return shareDTO != null ? JsonData.buildSuccess(shareDTO) : JsonData.buildError("创建分享失败");
    }

    /**
     * 取消分享接口
     * 接口功能：取消指定的分享链接，使其失效
     * 权限要求：登录用户，且只能取消自己创建的分享
     *
     * @param request 包含分享ID的请求对象
     * @return JsonData 响应结果，包含操作结果或错误信息
     */
    @Operation(
            summary = "取消分享",
            description = "取消指定的分享链接，使其失效，只能取消当前用户创建的分享",
            method = "POST",
            requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
                    description = "分享取消请求参数",
                    required = true,
                    content = @Content(schema = @Schema(implementation = ShareCancelRequest.class))
            )
    )
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "取消成功",
                    content = @Content(schema = @Schema(implementation = JsonData.class))),
            @ApiResponse(responseCode = "400", description = "参数错误或无权限取消",
                    content = @Content(schema = @Schema(implementation = JsonData.class))),
            @ApiResponse(responseCode = "500", description = "服务器内部错误",
                    content = @Content(schema = @Schema(implementation = JsonData.class)))
    })
    @PostMapping("/cancel")
    public JsonData cancelShare(
            @Parameter(required = true, description = "分享取消请求对象，包含需要取消的分享ID")
            @RequestBody ShareCancelRequest request) {
        // 从ThreadLocal中获取当前登录用户ID并设置到请求对象中
        Long accountNo = LoginInterceptor.threadLocal.get().getAccountNo();
        request.setAccountNo(accountNo);

        // 调用服务层方法取消分享
        boolean result = shareService.cancelShare(request);

        // 根据操作结果返回成功或错误响应
        return result ? JsonData.buildSuccess() : JsonData.buildError("取消分享失败");
    }





    /**
     * 访问分享接口 - 获取分享的基本信息
     * 无需验证权限，任何人可通过分享ID获取分享的基本元数据（不含敏感内容）
     *
     * @param shareId 分享ID，通过URL参数传递
     * @return JsonData 包含分享基本信息的响应对象
     */
    @Operation(
            summary = "访问分享获取基本信息",
            description = "通过分享ID获取分享的基本信息（如标题、创建者昵称等公开信息），无需验证权限",
            method = "GET",
            parameters = {
                    @Parameter(
                            name = "shareId",
                            in = ParameterIn.QUERY,
                            required = true,
                            description = "分享ID",
                            schema = @Schema(type = "long")
                    )
            }
    )
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "获取成功",
                    content = @Content(schema = @Schema(implementation = JsonData.class))),
            @ApiResponse(responseCode = "404", description = "分享不存在或已过期",
                    content = @Content(schema = @Schema(implementation = JsonData.class)))
    })
    @GetMapping("/visit")
    public JsonData visit(
            @Parameter(required = true, description = "分享唯一标识ID")
            @RequestParam("shareId") Long shareId) {

        // 调用服务层获取分享基本信息
        ShareSimpleDTO shareSimpleDTO = shareService.simpleDetail(shareId);

        return JsonData.buildSuccess(shareSimpleDTO);
    }


    /**
     * 校验分享码接口
     * 当分享为"需要提取码"类型时，用户需输入正确的分享码才能获取访问令牌
     * 验证通过后返回JWT令牌，用于后续访问分享详情
     *
     * @param request 包含分享ID和分享码的请求对象
     * @return JsonData 包含访问令牌或错误信息的响应对象
     */
    @Operation(
            summary = "校验分享提取码",
            description = "对需要提取码的分享进行验证，通过后返回访问令牌(share-token)用于后续操作",
            method = "POST",
            requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
                    description = "分享码校验请求参数",
                    required = true,
                    content = @Content(schema = @Schema(implementation = ShareCheckRequest.class))
            )
    )
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "验证成功，返回访问令牌",
                    content = @Content(schema = @Schema(implementation = JsonData.class))),
            @ApiResponse(responseCode = "400", description = "分享码错误或参数无效",
                    content = @Content(schema = @Schema(implementation = JsonData.class))),
            @ApiResponse(responseCode = "404", description = "分享不存在",
                    content = @Content(schema = @Schema(implementation = JsonData.class)))
    })
    @PostMapping("/check_share_code")
    public JsonData checkShareCode(
            @Parameter(required = true, description = "包含分享ID和提取码的请求对象")
            @RequestBody ShareCheckRequest request) {

        // 调用服务层验证分享码，返回访问令牌
        String token = shareService.shareCheckCode(request);

        return token != null ? JsonData.buildSuccess(token) : JsonData.buildError("校验失败");
    }


    /**
     * 查看分享详情接口
     * 需要验证访问权限（通过@ShareCodeCheck注解拦截校验share-token）
     * 返回分享的详细信息，包括分享的文件列表概览、创建时间、过期时间等
     *
     * @return JsonData 包含分享详情的响应对象
     */
    @Operation(
            summary = "查看分享详情",
            description = "获取分享的详细信息（需先通过分享码验证，在请求头中携带share-token）",
            method = "GET",
            parameters = {
                    @Parameter(
                            name = "share-token",
                            in = ParameterIn.HEADER,
                            required = true,
                            description = "通过分享码验证后获取的访问令牌",
                            schema = @Schema(type = "string")
                    )
            }
    )
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "获取成功",
                    content = @Content(schema = @Schema(implementation = JsonData.class))),
            @ApiResponse(responseCode = "401", description = "未授权访问（令牌无效或已过期）",
                    content = @Content(schema = @Schema(implementation = JsonData.class))),
            @ApiResponse(responseCode = "404", description = "分享不存在",
                    content = @Content(schema = @Schema(implementation = JsonData.class)))
    })
    @GetMapping("/detail")
    @ShareCodeCheck  // 使用自定义注解进行权限校验
    public JsonData detail() {
        // 从线程本地变量中获取通过切面验证的分享ID
        Long shareId = ShareCodeAspect.getShareId();
        // 调用服务层获取分享详情
        ShareDetailDTO shareDetailDTO = shareService.detail(shareId);

        return JsonData.buildSuccess(shareDetailDTO);
    }


    /**
     * 查看分享文件夹下的文件列表接口
     * 需要验证访问权限（通过@ShareCodeCheck注解拦截校验）
     * 支持分页查询，可获取指定文件夹下的文件列表
     *
     * @param request 包含文件夹ID和分页参数的请求对象
     * @return JsonData 包含文件列表的响应对象
     */
    @Operation(
            summary = "查询分享中的文件列表",
            description = "获取分享中指定文件夹下的文件列表（需在请求头中携带share-token）",
            method = "POST",
            requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
                    description = "文件列表查询参数（包含文件夹ID和分页信息）",
                    required = true,
                    content = @Content(schema = @Schema(implementation = ShareFileQueryRequest.class))
            ),
            parameters = {
                    @Parameter(
                            name = "share-token",
                            in = ParameterIn.HEADER,
                            required = true,
                            description = "访问令牌",
                            schema = @Schema(type = "string")
                    )
            }
    )
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "查询成功",
                    content = @Content(schema = @Schema(implementation = JsonData.class))),
            @ApiResponse(responseCode = "401", description = "未授权访问",
                    content = @Content(schema = @Schema(implementation = JsonData.class))),
            @ApiResponse(responseCode = "404", description = "分享或文件夹不存在",
                    content = @Content(schema = @Schema(implementation = JsonData.class)))
    })
    @PostMapping("/list_share_file")
    @ShareCodeCheck  // 权限校验
    public JsonData listShareFile(
            @Parameter(required = true, description = "文件查询请求参数，包含文件夹ID和分页信息")
            @RequestBody ShareFileQueryRequest request) {

        // 设置从线程中获取的分享ID到请求参数
        request.setShareId(ShareCodeAspect.getShareId());
        // 调用服务层查询文件列表
        List<AccountFileDTO> list = shareService.listShareFile(request);

        return list != null ? JsonData.buildSuccess(list) : JsonData.buildError("查询失败");
    }


    /**
     * 文件转存接口
     * 将分享中的文件转存到当前登录用户的存储空间
     * 需要验证分享访问权限和用户登录状态
     *
     * @param request 包含待转存文件ID和目标文件夹ID的请求对象
     * @return JsonData 转存操作结果的响应对象
     */
    @Operation(
            summary = "转存分享文件到我的空间",
            description = "将分享中的文件或文件夹转存到当前登录用户的存储空间（需登录且拥有分享访问权限）",
            method = "POST",
            requestBody = @io.swagger.v3.oas.annotations.parameters.RequestBody(
                    description = "文件转存请求参数（包含待转存文件ID和目标文件夹ID）",
                    required = true,
                    content = @Content(schema = @Schema(implementation = ShareFileTransferRequest.class))
            ),
            parameters = {
                    @Parameter(
                            name = "share-token",
                            in = ParameterIn.HEADER,
                            required = true,
                            description = "访问令牌",
                            schema = @Schema(type = "string")
                    ),
                    @Parameter(
                            name = "Authorization",
                            in = ParameterIn.HEADER,
                            required = true,
                            description = "用户登录令牌",
                            schema = @Schema(type = "string")
                    )
            }
    )
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "转存成功",
                    content = @Content(schema = @Schema(implementation = JsonData.class))),
            @ApiResponse(responseCode = "401", description = "未授权访问（用户未登录或分享令牌无效）",
                    content = @Content(schema = @Schema(implementation = JsonData.class))),
            @ApiResponse(responseCode = "403", description = "转存失败（如空间不足、文件已存在）",
                    content = @Content(schema = @Schema(implementation = JsonData.class))),
            @ApiResponse(responseCode = "404", description = "分享或文件不存在",
                    content = @Content(schema = @Schema(implementation = JsonData.class)))
    })
    @PostMapping("/transfer")
    @ShareCodeCheck
    public JsonData transfer(
            @Parameter(required = true, description = "文件转存请求参数，包含待转存文件ID和目标路径")
            @RequestBody ShareFileTransferRequest request) {

        // 设置分享ID和当前登录用户ID到请求参数
        request.setShareId(ShareCodeAspect.getShareId());
        Long accountNo = LoginInterceptor.threadLocal.get().getAccountNo();
        request.setAccountNo(accountNo);

        // 调用服务层执行转存操作
        Boolean result = shareService.transferShareFile(request);

        return result ? JsonData.buildSuccess() : JsonData.buildError("转存失败");
    }
}




